package labb3;

import labb3.FileHandling.FileChooser;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;

/**
 * Creates and construct a GUI with two panels and a menu.
 *
 * @author Mikko Puustinen
 * @version 0.1, 2007-okt-07
 */
public class GUI {
    private final MediaController controller;
    private final MediaListPanel listpanel;
    private final CenterPanel centerpanel;
    private static final String VERSION = "";
    private static final String CHANGED = "(Changed)";
    private JFrame frame;
    private FileChooser fc;

    static {
        try {
            String lookAndFeel = UIManager.getSystemLookAndFeelClassName();
            UIManager.setLookAndFeel(lookAndFeel);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Creates a standard GUI.
     *
     * @param collection MediaCollection to use.
     * @param controller MediaController to use.
     */
    public GUI(MediaCollection collection, MediaController controller) {
        this.controller = controller;
        centerpanel = new CenterPanel();
        listpanel = new MediaListPanel(this, centerpanel, collection.getCollectionClone());
        collection.addListener(listpanel);
        createGUI();
    }

    /**
     * Create the GUI.
     */
    private void createGUI() {
        frame = new JFrame();
        JSplitPane splitPane;

        frame.setJMenuBar(new Menu(this).constructMenuBar());
        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, listpanel, centerpanel);
        splitPane.setDividerLocation(200);
        fc = new FileChooser(frame);

        frame.setTitle("mazORG " + VERSION);
        frame.add(splitPane);
        frame.pack();
        frame.setMinimumSize(new Dimension(500, 400));
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new GUIWindowListener());
    }

    /**
     * Exit the program. If there is any changes made to the list (Added/deleted
     * etc.) a dialog will prompt the user to save.
     */
    public void exitProgram() {
        if (controller.isCollectionChanged()) {
            int i = JOptionPane.showConfirmDialog(frame, "Do you want to save your changes?", "Collection has been modified", JOptionPane.YES_NO_CANCEL_OPTION);
            if (i == 2)
                return;
            else if (i == 0) {
                saveAs();
            }
        }
        frame.dispose();
    }

    /**
     * Shows an "Add media" dialog which then let the user add the information
     * about a Media.
     */
    public void addMedia() {
        new AddEditMedia(frame.getLocation(), controller).inputDialog();
    }

    /**
     * Shows an edit dialog for the selected Media.
     */
    public void editMedia() {
        new AddEditMedia(frame.getLocation(), controller, listpanel.getSelectedMedia()).inputDialog();
    }

    /**
     * Removes the specified Media.
     *
     * @param media Media to remove
     */
    public void removeMedia(Media media) {
        int i = JOptionPane.showConfirmDialog(frame, "Remove \"" + media.getTitle() + "\"?", "Remove from collection", JOptionPane.OK_OPTION);
        if (i == 0)
            controller.removeMedia(media);
    }

    /**
     * Removes the selected Media.
     */
    public void removeMedia() {
        Media media;
        try {
            media = listpanel.getSelectedMedia();
        } catch (IndexOutOfBoundsException e) {
            return;
        }
        int i = JOptionPane.showConfirmDialog(frame, "Remove \"" + media.getTitle() + "\"?", "Remove from collection", JOptionPane.OK_OPTION);
        if (i == 0)
            controller.removeMedia(media);
    }

    /**
     * Searches thru the MediaCollection for the string.
     *
     * @param string search string.
     */
    public void search(String string) {
        controller.search(string);
    }

    /**
     * Sort the MediaCollection.
     */
    public void sortList() {
        controller.sort();
    }

    /**
     * Saves the MediaCollection to the specified location.
     */
    public void saveAs() {
        String path = fc.saveAs();
        if (path == null)
            return;
        if (new File(path).exists()) {
            int i = JOptionPane.showConfirmDialog(frame, "File exist, overwrite?", "Overwrite file?", JOptionPane.OK_OPTION);
            if (i > 0)
                return;
        }
        try {
            controller.saveCollection(fc.getPath());
        } catch (IOException e) {
            JOptionPane.showMessageDialog(frame, "Could not save:\n" + e.getMessage());
        }
    }

    /**
     * Saves the MediaCollection.
     */
    public void save() {
        try {
            controller.saveCollection();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(frame, "Could not save:\n" + e.getMessage());
        }
    }

    /**
     * Loads a MediaCollection.
     */
    public void open() {
        String path = null;
        try {
            path = fc.openDialog();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(frame, "Could not open:\n" + e.getMessage());
        }
        if (path == null)
            return;

        try {
            controller.loadCollection(path);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(frame, "Could not open:\n" + e.getMessage());
        } catch (ClassNotFoundException e) {
            //
        }
    }

    /**
     * Shows an "About" dialog.
     */
    public void showAbout() {
        new AboutDialog(frame);
    }

    private class GUIWindowListener extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
            exitProgram();
        }
    }
}
